#include <logger.hpp>
#include <fstream>
#include "CmdHandler.h"
#include <stdint.h>

void CQueryCmdHandler::writeStatusHeader()
{
    LOG(DEBUG, "CQueryCmdHandler::writeStatusHeader");
    LOG(DEBUG, "open dbp status file "<<dbpStatsFile_);
    std::ofstream outf(dbpStatsFile_.c_str());
    if(!outf.is_open()){
        LOG(ERROR, "cannot open dbp status file="<<dbpStatsFile_);
    }else{
        outf<<"Time"
            <<"\t"<<"insertQue_.Size()"<<"\t"<<"insertQue_.TopSize()"
            <<"\t"<<"insertSuccStats_"
            <<"\t"<<"insertSuccTimeUs_"
            <<"\t"<<"insertSuccAveTimeUs_"
            <<"\t"<<"insertFailStats_"
            <<"\t"<<"insertFailTimeUs_"
            <<"\t"<<"insertFailAveTimeUs_"
            <<"\t"<<"scanOpenStats_"
            <<"\t"<<"scanOpenTimeUs_"
            <<"\t"<<"scanOpenAveTimeUs_"
            <<"\t"<<"scanNextStats_"
            <<"\t"<<"scanNextTimeUs_"
            <<"\t"<<"scanNextAveTimeUs_"
            <<"\t"<<"CommandStats"
            <<std::endl;
    }
}

void CQueryCmdHandler::writeStatus()
{
    LOG(DEBUG, "CQueryCmdHandler::writeStatus");
    LOG(DEBUG, "open dbp status file "<<dbpStatsFile_<<" and write");
    std::ofstream outf(dbpStatsFile_.c_str(),std::ios_base::app);
    if(!outf.is_open()){
        LOG(ERROR, "cannot open dbp status file="<<dbpStatsFile_);
    }else{
        outf<<Tools::TimeString(time(0));
        outf<<"\t"<<insertQue_.Size()<<"\t"<<insertQue_.TopSize();
        uint32_t succ = dbpStats_->insertSuccStats_;
        uint32_t fail = dbpStats_->insertFailStats_;
        uint64_t succ_time = dbpStats_->insertSuccTime_;
        uint64_t fail_time = dbpStats_->insertFailTime_;
        uint32_t sopen = dbpStats_->scanOpenStats_;
        uint64_t sopen_time = dbpStats_->scanOpenTime_;
        uint32_t snext = dbpStats_->scanNextStats_;
        uint64_t snext_time = dbpStats_->scanNextTime_;
        dbpStats_->Reset();
        outf<<"\t"<<succ
            <<"\t"<<succ_time
            <<"\t"<<(succ ? (succ_time / succ) : 0)
            <<"\t"<<fail
            <<"\t"<<fail_time
            <<"\t"<<(fail ? (fail_time / fail) : 0)
            <<"\t"<<sopen
            <<"\t"<<sopen_time
            <<"\t"<<(sopen ? (sopen_time / sopen) : 0)
            <<"\t"<<snext
            <<"\t"<<snext_time
            <<"\t"<<(snext ? (snext_time / snext) : 0)
            ;
        {   //Command Stats
            CMutexGuard g(cmdStats_.Mutex());
            for(__CmdStats::iterator it = cmdStats_.begin();it != cmdStats_.end();++it)
                outf<<"\t"<<QCmdBase::CommandName(it->first)<<","<<it->second.first
                <<","<<it->second.second;
            cmdStats_.clear();
        }
        outf<<std::endl;
        outf.close();
        insertQue_.ResetTopSize();
    }
}

void * CQueryCmdHandler::DbpStatsThread(void * arg)
{
    LOG(DEBUG, "CQueryCmdHandler::DbpStatsThread");
    //ASSERT(arg != 0,"invalid arg");
    
    CQueryCmdHandler & self = *(CQueryCmdHandler *)arg;
    self.writeStatusHeader();       //Dbp Status header
    for(;;){
        sleep(self.dbpStatsTimeInterval_);
        self.writeStatus();         //Dbp Status
    }
    return 0;
}
